//
//  BlueManager.m
//  WealthGoods
//
//  Created by yisheng chen on 2023/11/28.
//

#import "BlueManager.h"
#import "BlueCommonData.h"
@interface BlueManager()<CBCentralManagerDelegate,CBPeripheralDelegate>

@property(nonatomic,strong) CBCentralManager *cbcManager;
@property(nonatomic,strong) CBCharacteristic *writC;
@property(nonatomic,strong) CBPeripheral *peripheral;
@property (nonatomic,strong) NSMutableArray *dataArray;
@property (nonatomic,copy) NSString *fileStr;
@property (nonatomic,copy) NSData *fileData;
@end

@implementation BlueManager
static BlueManager *manager = nil;

- (instancetype)init
{
    self = [super init];
    if (self) {
        //这里centralManager需要设置CBCentralManagerDelegate,CBPeripheralDelegate这两个代理
        _dataArray = [[NSMutableArray alloc] init];
        _cbcManager = [[CBCentralManager alloc]initWithDelegate:self queue:nil options:nil];
    }
    return self;
}

+ (instancetype)shareInstance
{
    //这里是通过GCD的once方法实现单例的创建，该方法在整个应用程序中只会执行一次，所以经常用作单例的创建。
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [[self alloc] init];
    });
    
    return manager;
}
//开始扫描蓝牙
- (void)startScan{
    [self.cbcManager scanForPeripheralsWithServices:nil options:nil];
}
//停止扫描蓝牙
- (void)stopScan{
    [self.cbcManager stopScan];
}
//选中的蓝牙
- (void)selectPeripheral:(CBPeripheral *)peripheral{
    [self.cbcManager connectPeripheral:peripheral options:nil];
}
#pragma mark 蓝牙代理方法
- (void)centralManagerDidUpdateState:(CBCentralManager *)central {
    //    NSLog(@"蓝牙状态 - %d",central.state);
    switch (central.state) {
        case 4:
//            [SkToast SkToastShow:@"Please turn on Bluetooth first"];
            break;
        case 5://蓝牙打开状态，扫描蓝牙设备
//            [SkToast SkToastShow:@"Bluetooth turned on"];
            break;
        default:
            break;
    }
}
//扫描到Peripherals
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI {
    [self.dataArray addObject:peripheral];
    //过滤指定的客户标识
    NSLog(@"----------%@",peripheral.name);
    if (!isNilString(peripheral.name)) {
        [self.dataArray addObject:peripheral];
//        [self.delegate deviceList:self.dataArray];
    }
    return;
    
}
//连接到Peripherals-成功
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
    [central stopScan];
    [SkToast SkToastShow:@"Successfully connected to Bluetooth"];
    peripheral.delegate = self;
    [peripheral discoverServices:nil];
    self.peripheral = peripheral;
}
//连接到Peripherals-失败
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
    NSLog(@"连接Peripherals 失败     %@",error);
    [SkToast SkToastShow:@"Connection failure"];
    
}
//Peripherals断开连接
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
    NSLog(@"断开连接 - %@",error);
    //    [self.loadView stopLoading];
    [SkToast SkToastShow:@"Break link"];
}
//扫描到服务
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error {
    [SkToast SkToastShow:@"Bluetooth connected"];
    //发现所有服务
    for (CBService *service in peripheral.services) {
        [peripheral discoverCharacteristics:nil forService:service];
    }
}
//发现服务的Characteristics
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error {
    for (CBCharacteristic *c in service.characteristics){
        //遍历特征值
        NSLog(@"c------%@",c.UUID.UUIDString);
        if ([c.UUID.UUIDString isEqualToString:@"0783B03E-8535-B5A0-7140-A304D2495CB8"]) {
            [peripheral setNotifyValue:YES forCharacteristic:c];
//            [SkToast SkToastShow:@"发现读的特征"];
        }
        if ([c.UUID.UUIDString isEqualToString:@"FFF3"]){
//            [SkToast SkToastShow:@"发现写的特征"];
            self.writC = c;
        }
    }
    //暂时无用
//    [self.cArray addObjectsFromArray:service.characteristics];
    
}
#pragma mark - - (监听服务端回复的消息)
//读取Characteristics的值
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
    
    NSMutableData *data = [NSMutableData dataWithData:characteristic.value];
    
    Byte *valueByte = (Byte *)[data bytes];
    NSLog(@"收到的数据- %@     %ld      %@",data,data.length,[self hexString:data]);
    for (int i = 0; i < data.length - 1; i++) {
        NSLog(@"转换%x",valueByte[i]);
        //文档1.3：设备的响应更新及请求文件数据0x03
        if(i == 2 && valueByte[2] == 3){
            NSData *decryptData = [data subdataWithRange:NSMakeRange(3, 4)];
            NSString *str = [self hexString:decryptData];
            NSLog(@"-------%@",str);
            [self writeOneAndTwoDevice:[self characterTo16:str]];
            break;
        }
        
        //文档2.2：回应校验
        if(i == 2 && valueByte[2] == 4){
//            [SkToast SkToastShow:@"收到校验"];
            [self writeTwoAndOneDevice];
            break;
        }
    }
    //先把收到的数据求出总和，校验数据是否正确，数据正确后再进行下一步操作
}
#pragma mark - - 1.1 APP端发起更新(获取文件大小)
-(void)writeOneAndOneDevice{
    NSData * fileData = [self getFileData];
    NSData *data = [BlueCommonData createFirmwareUpdatePacketWithFileSize:fileData.length];
    [self writeBluetooth:data];
}
#pragma mark - - 1.2 APP端回复数据指令(即继续传输文件data,每次最多只传384)
-(void)writeOneAndTwoDevice:(NSInteger)location{
    NSData * fileData = [self getFileData];
    if(fileData.length - location <= 384){
        [SkToast SkToastShow:@"Upload picture successfully"];
    }
    kWeakSelf(weakSelf);
    [BlueCommonData sendDataPacket:fileData andLocation:location andBlock:^(NSData * _Nonnull blueData) {
        [weakSelf writeBluetooth:blueData];
    }];
}
#pragma mark - - 1.3 服务端回复 不需要
-(void)writeOneAndThreeDevice{
    
}
#pragma mark - - 2.1 发起校验
-(void)writeTwoAndOneDevice{
    NSData *data = [BlueCommonData buildCommandPacketWithVersion:0x5AA5];
    [self writeBluetooth:data];
}
#pragma mark - - 2.2  回应验证 （服务端回复 不需要）
-(void)writeTwoAndTwoDevice{
//    NSData *data = [BlueCommonData buildResponsePacket];
//    [self writeBluetooth:data];
}
#pragma mark - - 写入蓝牙(写消息给服务端)
- (void)writeBluetooth:(NSData *)data{
    if (self.writC.properties & CBCharacteristicPropertyWriteWithoutResponse) {
        [self.peripheral writeValue:data forCharacteristic:self.writC type:CBCharacteristicWriteWithoutResponse];
        NSLog(@"写入蓝牙数据1");
    }else{
        NSLog(@"写入蓝牙数据2");
        [self.peripheral writeValue:data forCharacteristic:self.writC type:CBCharacteristicWriteWithResponse];
    }
}

#pragma mark - - 转16进制转10进制
-(NSInteger)characterTo16:(NSString *)hexString{
    
    NSScanner *scanner = [NSScanner scannerWithString:hexString];
    unsigned int decimalValue;
    [scanner scanHexInt:&decimalValue];
    return decimalValue;
}
#pragma mark - - data转16进制字符串
- (NSString *)hexString:(NSData *)data {
    NSUInteger length = data.length;
    NSMutableString *result = [NSMutableString stringWithCapacity:length * 2];
    const unsigned char *byte = data.bytes;
    for (int i = 0; i < length; i++, byte++) {
        [result appendFormat:@"%02X", *byte];
    }
    return result;
}

#pragma mark - - 获取文件data
- (NSData *)getFileData{
//    NSURL *fileUrl = [[NSBundle mainBundle] URLForResource:self.fileStr withExtension:nil];
    return self.fileData;
}
- (void)setBlueFileData:(NSData *)data{
    self.fileData = data;
}
- (void)setFileName:(NSString *)fileName{
    self.fileStr = fileName;
}
- (CBPeripheral *)getBluePeripheral{
    return self.peripheral;
}
@end
